import { modifyCSS, createDom } from '@antv/dom-util';
import { isString } from '@antv/util';
import insertCss from 'insert-css';
import PluginBase from '@/graph/plugins/Base';

typeof document !== 'undefined' && insertCss(
  `.g6-component-contextmenu {
    padding: 5PX 0;
    margin: 0;
    font-size: 14px;
    color: #606266;
    font-weight: 400;
    display: inline-block;
    box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.5);
    border: 1px solid #ebeef5;
    border-radius: 2px;
    font-family: Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,SimSun,sans-serif;
    -webkit-font-smoothing: antialiased;
    -webkit-tap-highlight-color: transparent;
  }

  .g6-component-contextmenu ul.g6-contextmenu-ul {
    list-style: none;
    padding: 0;
    margin: 0;
    background-color: #fff;
  }

  .g6-component-contextmenu ul li {
    text-indent: 1em;
    height: 24px;
    width: 100px;
    line-height: 24px;
    padding: 0;
    cursor: pointer;
    position: relative;
    box-sizing: content-box;
  }

  .g6-component-contextmenu ul li::after {
    content: "";
    position: absolute;
    top: 90%;
    left: 5%;
    width: 90%;
    height: 1px;
    background-color: #ebeef5;
    z-index: 1;
  }

  .g6-component-contextmenu ul li:last-child::after {
    background-color: unset;
  }

  .g6-component-contextmenu ul li:hover {
    background-color: #e8e8e9;
  }`
);

export default class Menu extends PluginBase {

  constructor(cfg) {
    super(cfg);
  }

  getDefaultCfg() { return { container: null }; }

  init() {
    const className = this.get('className');
    const menu = createDom("<div class=".concat(className || 'g6-component-contextmenu', "></div>"));
    modifyCSS(menu, { top: '0px', position: 'absolute', visibility: 'hidden' });
    let container = this.get('container');
    if (!container) {
      container = this.get('graph').get('container');
    }
    if (isString(container)) {
      container = document.getElementById(container);
    }
    container.appendChild(menu);
    this.set('menu', menu);
  };

  getDefaultCfgs() {
    return {
      offsetX: 6,
      offsetY: 6,
      handleMenuClick: undefined,
      getContent(e) {
        return `
          <ul class='g6-contextmenu-ul'>
          <li>\u83DC\u5355\u98791</li>
          <li>\u83DC\u5355\u98792</li>
          </ul>`;
      },
      shouldBegin(e) { return true },
      onHide() { return true; },
      itemTypes: ['node', 'edge', 'combo'],
      trigger: 'contextmenu'
    };

  }

  getEvents() {
    if (this.get('trigger') === 'click') {
      return { click: 'onMenuShow', touchend: 'onMenuShow' };
    }
    return { contextmenu: 'onMenuShow' };
  }

  onMenuShow(e) {
    const self = this;
    e.preventDefault();
    const itemTypes = this.get('itemTypes');
    debugger
    if (!e.item) {
      if (itemTypes.indexOf('canvas') === -1) return self.onMenuHide();
    } else {
      if (e.item && e.item.getType && itemTypes.indexOf(e.item.getType()) === -1) return self.onMenuHide();
    }
    const shouldBegin = this.get('shouldBegin');
    if (!shouldBegin(e)) return;
    const menuDom = this.get('menu');
    const getContent = this.get('getContent');
    const graph = this.get('graph');
    const menu = getContent(e, graph);
    if (isString(menu)) {
      menuDom.innerHTML = menu;
    } else {
      menuDom.innerHTML = menu.outerHTML;
    }

    this.removeMenuEventListener();// 清除之前监听的事件
    const handleMenuClick = this.get('handleMenuClick');
    if (handleMenuClick) {
      const handleMenuClickWrapper = function handleMenuClickWrapper(evt) {
        handleMenuClick(evt.target, e.item, graph);
      };
      this.set('handleMenuClickWrapper', handleMenuClickWrapper);
      menuDom.addEventListener('click', handleMenuClickWrapper);
    }
    const width = graph.get('width');
    const height = graph.get('height');
    const bbox = menuDom.getBoundingClientRect();
    const offsetX = this.get('offsetX') || 0;
    const offsetY = this.get('offsetY') || 0;
    const graphTop = graph.getContainer().offsetTop;
    const graphLeft = graph.getContainer().offsetLeft;
    let x = e.canvasX + graphLeft + offsetX;
    let y = e.canvasY + graphTop + offsetY;

    if (x + bbox.width > width) {// 当菜单(部分)脱离画布时
      x = e.canvasX - bbox.width - offsetX + graphLeft;
    }
    if (y + bbox.height > height) {
      y = e.canvasY - bbox.height - offsetY + graphTop;
    }
    modifyCSS(menuDom, { top: "".concat(y, "px"), left: "".concat(x, "px"), visibility: 'visible' });

    const triggeredByFirstClick = this.get('trigger') === 'click';// 左键单击会触发 body 上监听的 click 事件，导致菜单展示出来后又立即被隐藏了，需要过滤掉
    const handler = function handler(evt) {
      if (triggeredByFirstClick) {
        triggeredByFirstClick = false;
        return;
      }
      self.onMenuHide();
    };
    // 如果在页面中其他任意地方进行click, 隐去菜单
    document.body.addEventListener('click', handler);
    this.set('handler', handler);

  }
  removeMenuEventListener() {
    const handleMenuClickWrapper = this.get('handleMenuClickWrapper');
    const handler = this.get('handler');
    if (handleMenuClickWrapper) {
      const menuDom = this.get('menu');
      menuDom.removeEventListener('click', handleMenuClickWrapper);
      this.set('handleMenuClickWrapper', null);
    }
    if (handler) {
      document.body.removeEventListener('click', handler);
    }
  }

  onMenuHide() {
    const menuDom = this.get('menu');
    if (menuDom) {
      modifyCSS(menuDom, { visibility: 'hidden' });
    }

    this.removeMenuEventListener();// 隐藏菜单后需要移除事件监听
  }

  destroy() {
    const menu = this.get('menu');
    this.removeMenuEventListener();
    if (menu) {
      const container = this.get('container');
      if (!container) {
        container = this.get('graph').get('container');
      }
      if (isString(container)) {
        container = document.getElementById(container);
      }
      container.removeChild(menu);
    }
  }

}